package com.android.ripplewave;

import android.content.Context;
import android.view.View;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Color;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.view.MotionEvent;

public class RippleWaveView extends View implements Runnable{
	
	private Thread run_thread;
	private boolean thread_can_run;
	private Paint paint;
	private int screen_width, screen_height;
	
	int image_width,image_height,half_width,half_height;
    // MemoryImageSource source_image;
    // Image display_image, offImage;
    // Graphics offGraphics;
	private Bitmap original_image, ripple_image;
	private int [] original_image_data, ripple_image_data;
	private int [] buffer_one, buffer_two, buffer_tmp;
	private int image_data_length;
	
	
	
    int tmp_i,bound_a,bound_b;
    int touch_x,touch_y;
    int image_size;
	
	int ripplemap[];
    int texture[];
    int ripple[];
    int oldind,newind,mapind;
    int riprad;
	
	private int frame_count = 0;
	private int FPS = 0;
	private long frame_count_start_time = 0;
	// public RippleWaveSurfaceView(Context context, int screen_width, int screen_height){
	public RippleWaveView(Context context){
		super(context);		
		paint = new Paint();
		// this.screen_width = screen_width;
		// this.screen_height = screen_height;
		screen_width = context.getResources().getDisplayMetrics().widthPixels;
		screen_height = context.getResources().getDisplayMetrics().heightPixels;
		original_image = BitmapFactory.decodeResource(getResources(), R.drawable.lotus);
		image_width = screen_width;
		image_height = screen_height;
		
		half_width = image_width>>1;
        half_height = image_height>>1;
        riprad=3;
        image_size = image_width * (image_height+2) * 2;
        ripplemap = new int[image_size];		
        ripple = new int[image_width*image_height];
        texture = new int[image_width*image_height];        
        oldind = image_width;
        newind = image_width * (image_height+3);
		original_image.getPixels(texture, 0, image_width, 0, 0, image_width, image_height);
	}
	
	@Override
	protected void onDraw(Canvas canvas){
		paint.setColor(Color.WHITE);
		canvas.drawRect(0, 0, screen_width, screen_height, paint);
		paint.setColor(Color.BLACK);
		// canvas.drawText("hello ripple", 50, 50, paint);
		
		// newframe();
		// ripple_image = Bitmap.createBitmap(ripplemap, image_width, image_height, Config.ARGB_8888);
		canvas.drawBitmap(original_image, 0, 0, paint);
		// if(ripple_image != null)
			// canvas.drawBitmap(ripple_image, 0, 0, paint);
		canvas.drawText("FPS: " + FPS, screen_width - 100, 50, paint);
		
		
		
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) 
	{	
		super.onTouchEvent(event);
		touch_x = (int)event.getX();
		touch_y = (int)event.getY();
		disturb(touch_x, touch_y);
		return true;
	}
	
	public void Initalize(){
		run_thread = new Thread(this);
		run_thread.start();
		thread_can_run = true;	
	}
	
	public void Destroy(){
		boolean retry = true;
		thread_can_run = false;
        do {
            try {
                run_thread.join();
                retry = false;
            } catch (InterruptedException e) {
				e.printStackTrace();
                // we will try it again and again...
            }
        }while(retry);
		
	}
	
	public void run(){
		while(thread_can_run){
			if(System.currentTimeMillis() - frame_count_start_time < 1000){
				frame_count ++;
			}else{
				FPS = frame_count;
				frame_count = 0;
				frame_count_start_time = System.currentTimeMillis();
			}
			newframe();
			ripple_image = Bitmap.createBitmap(ripple, image_width, image_height, Config.ARGB_8888);					
			postInvalidate();
		}
	}
	
	public void disturb(int touch_x, int touch_y) {
		for (int j=touch_y-riprad;j<touch_y+riprad;j++) {
			for (int k=touch_x-riprad;k<touch_x+riprad;k++) {
				if (j>=0 && j<image_height && k>=0 && k<image_width) {
					ripplemap[oldind+(j*image_width)+k] += 512;
				}
			}
		}
    }

    public void newframe() {
      //Toggle maps each frame
      tmp_i=oldind;
      oldind=newind;
      newind=tmp_i;

      tmp_i=0;
      mapind=oldind;
      for (int y=0;y<image_height;y++) {
        for (int x=0;x<image_width;x++) {
			short data = (short)((ripplemap[mapind-image_width]+ripplemap[mapind+image_width]+ripplemap[mapind-1]+ripplemap[mapind+1])>>1);
			data -= ripplemap[newind+tmp_i];
			data -= data >> 5;
			ripplemap[newind+tmp_i]=data;

			//where data=0 then still, where data>0 then wave
			data = (short)(1024-data);

			//offsets
			bound_a=((x-half_width)*data/1024)+half_width;
			bound_b=((y-half_height)*data/1024)+half_height;

          
			//bounds check
			if (bound_a>=image_width) bound_a=image_width-1;
			if (bound_a<0) bound_a=0;
			if (bound_b>=image_height) bound_b=image_height-1;
			if (bound_b<0) bound_b=0;
          

			ripple[tmp_i]=texture[bound_a+(bound_b*image_width)];			
			mapind++;
			tmp_i++;
        }
      }
    }	
}